package jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.ArrayList;
import java.util.List;

import fachlogik.Haendler;
import fachlogik.Produkt;
import fachlogik.Shop;
import fachlogik.ShopException;

public class JdbcShop implements Shop
{
	private Connection connection;
	
	
	public JdbcShop() throws ShopException
	{
		getConnection();
	}
	
	private Connection getConnection() throws ShopException
	{
		try
		{
			if (connection == null || connection.isClosed())
			{
				String driver = "com.mysql.jdbc.Driver";
				String url = "jdbc:mysql://localhost/test";
				String user = "pos";
				String pwd = "pos";
				
				Class.forName(driver);
				connection = DriverManager.getConnection(url, user, pwd);
				
			}
		} catch (SQLException e)
		{
			throw new ShopException("Fehler beim Verbinden zur Datenbank", e);
		} catch (ClassNotFoundException e)
		{
			throw new ShopException("DB-Treiber nicht gefunden", e);
		}
		return connection;
	}
	

	@Override
	public void speichern(Produkt p) throws ShopException
	{
		if (p.getId() == 0)
			insert(p);
		else
			update(p);
	}
	
	private void update(Produkt p)
	{
		String sql = "UPDATE produkte SET" +
				" bezeichnung = ?, " +
				" ablaufdatum = ?," +
				" preis = ? " +
				" WHERE id = ?";
		
		// if (pstmt.executeUpdate() != 1)
		//		throw new ....
		
	}

	private void insert(Produkt p) throws ShopException
	{
		String sql = "INSERT INTO produkte " +
				" (bezeichnung, ablaufdatum, preis, fk_haendler_id) " +
				"VALUES (?, ?, ?, ?)";
		try(PreparedStatement pstmt = 
				getConnection().prepareStatement(sql, Statement.RETURN_GENERATED_KEYS))
		{		
			pstmt.setString(1, p.getBezeichnung());
			long millis = p.getAblaufdatum().getTime(); // Millisekunden seit 1.1.1970
			java.sql.Date ablaufdatum = new java.sql.Date(millis);
			pstmt.setDate(2, ablaufdatum);
			pstmt.setFloat(3, p.getPreis());
			if (p.getAnbieter() != null)
				pstmt.setInt(4, p.getAnbieter().getId());
			else
				pstmt.setNull(4, Types.INTEGER);
			pstmt.executeUpdate();
			ResultSet generated = pstmt.getGeneratedKeys();
			if (generated.next())
				p.setId(generated.getInt(1));
			else
				throw new ShopException("Fehler beim Auslesen des Auto-Werts");
			generated.close();
			
		} catch (SQLException e)
		{
			throw new ShopException("Fehler beim Speichern ", e);
		}
		
	}

	@Override
	public List<Produkt> alleProdukte() throws ShopException
	{
		List<Produkt> liste = null;
		String sql = "SELECT id, bezeichnung, ablaufdatum, preis " +
				" FROM produkte";
		
		try(PreparedStatement pstmt = getConnection().prepareStatement(sql);
				ResultSet rs = pstmt.executeQuery())
		{
			liste = produktListeVonResultSet(rs);
			rs.close();
			
		} catch (SQLException e)
		{
			throw new ShopException("Fehler beim Laden der Produkte", e);
		}
		
		return liste;
	}
	
	
	private List<Produkt> produktListeVonResultSet(ResultSet rs) throws SQLException
	{
		List<Produkt> liste = new ArrayList<>();
		while (rs.next())
		{
			Produkt p = new Produkt();
			int id = rs.getInt("id");
			p.setId(id);
			p.setBezeichnung(rs.getString("bezeichnung"));
			p.setAblaufdatum(rs.getDate("ablaufdatum"));
			p.setPreis(rs.getFloat("preis"));
			liste.add(p);
		}
		return liste;
	}

	@Override
	public List<Produkt> suchen(String suchText) throws ShopException
	{
		List<Produkt> liste = null;
		String sql = "SELECT id, bezeichnung, ablaufdatum, preis " +
				" FROM produkte WHERE LOWER(bezeichnung) LIKE ?";
		
		try (PreparedStatement pstmt = getConnection().prepareStatement(sql))
		{
			pstmt.setString(1, suchText.toLowerCase() + "%");
			ResultSet rs = pstmt.executeQuery();
			liste = produktListeVonResultSet(rs);
			rs.close();
		} catch (SQLException e)
		{
			throw new ShopException("Fehler beim Auslesen", e);
		}

		return liste;
	}

	@Override
	public void loeschen(Produkt p) throws ShopException
	{
		// TODO Auto-generated method stub
		
	}

	@Override
	public void beenden() throws ShopException
	{
		if (connection != null)
		{
			try
			{
				connection.close();
			} catch (SQLException e)
			{
				throw new ShopException("Fehler beim Beenden der DB-Verbindung", e);
			}
		}
		
	}

	@Override
	public void speichern(Haendler h) throws ShopException
	{
		if (h.getId() == 0)
			insert(h);
		else
			update(h);	
		
		// das ist nicht unbedingt notwendig (Frage des Konzepts)
		for (Produkt p : h.getAngebot())
			speichern(p);
	}

	private void update(Haendler h)
	{
		// wie bei Produkt
		
	}

	private void insert(Haendler h)
	{
		// wie bei Produkt
		
	}

	@Override
	public List<Haendler> alleHaendler() throws ShopException
	{
		// TODO Auto-generated method stub
		return null;
	}

}
